HAL SD typical use cases for migration ¶
This section provides information about HAL SD use cases for STM32 HAL1 to HAL2 migration.
Note
The typical read and write operations—whether using polling, DMA, or interrupt (IT) modes—remain largely unchanged for the user between HAL1 and HAL2. The main difference in HAL2 is the refactored callback registration and handling model: transfer completion callbacks are now unified and event-driven, simplifying application code.
The most significant changes in HAL2 are in linked-list DMA management. Linked-list operations now use a generic HAL Q API for node and queue management. HAL Q is a new HAL layer introduced in HAL2 that provides advanced linked-list features shared across multiple HAL drivers. It centralizes linked-list management, improving code reuse and maintainability.
Card removal/insertion handling differs from HAL1 to HAL2:
With HAL1, in the event of card plug-in/plug-off, the user should call
HAL_SD_InitCard()upon the card insertion.With HAL2 the application calls
HAL_SD_NotifyCardRemoval()on removal to reset the peripheral to default configuration andHAL_SD_NotifyCardInsertion()on insertion to initialize the card and apply user configuration.
HAL SD polling transfer mode ¶
This transfer sequence in polling mode remains unchanged between HAL1 and HAL2.
uint8_t Buffer_Block_Tx[BufferWordsSize], Buffer_Block_Rx[BufferWordsSize];
/* Write one block then read back (polling) */
SD_state = HAL_SD_Erase(&hsd_card, BlockStartAdd, BlockEndAdd);
/* Wait for the card transfer status */
while(HAL_SD_GetCardState(&hsd_card) != HAL_SD_CARD_TRANSFER)
{}
if (SD_state == HAL_OK)
{
/* Write NumberOfBlocks blocks of BufferWordsSize bytes on address BlockAddress */
SD_state = HAL_SD_WriteBlocks(&hsd_card, Buffer_Block_Tx, BlockAddress, NumberOfBlocks, UserTimeout_ms);
}
else
{
Error_Handler();
}
/* Wait for the card transfer status before starting a read operation */
while(HAL_SD_GetCardState(&hsd_card) != HAL_SD_CARD_TRANSFER)
{}
if (SD_state == HAL_OK)
{
/* Read NumberOfBlocks blocks of BufferWordsSize bytes from address BlockAddress */
SD_state = HAL_SD_ReadBlocks(&hsd_card, Buffer_Block_Rx, BlockAddress, NumberOfBlocks, UserTimeout_ms);
}
else
{
Error_Handler();
}
/* Wait for the card transfer status */
while(HAL_SD_GetCardState(&hsd_card) != HAL_SD_CARD_TRANSFER)
{}
HAL SD IT transfer mode ¶
|
HAL1 |
HAL2 |
|---|---|
|
IT transfer mode uses
|
IT transfer sequence remains mostly unchanged between HAL1 and HAL2, but callback registration is unified via
|
Code Snippet (IT)
|
HAL1 |
HAL2 |
|---|---|
uint8_t Buffer_Block_Tx[BufferWordsSize];
uint8_t Buffer_Block_Rx[BufferWordsSize];
/* Register the Tx and Rx
Transfer complete callbacks */
HAL_SD_RegisterCallback(&hsd_card,
HAL_SD_TX_CPLT_CB_ID,
TxCpltCallback);
HAL_SD_RegisterCallback(&hsd_card,
HAL_SD_RX_CPLT_CB_ID,
RxCpltCallback);
/* Write NumberOfBlocks blocks of BufferWordsSize
bytes on address BlockAddress */
SD_state = HAL_SD_WriteBlocks_IT(&hsd_card,
Buffer_Block_Tx,
BlockAddress,
NumberOfBlocks);
/* Wait for the Writing process to complete */
while(sdtransfertx == 0)
{}
/* Wait for the card transfer status before
starting a read operation */
while(HAL_SD_GetCardState(&hsd_card)
!= HAL_SD_CARD_TRANSFER)
{}
if (SD_state == HAL_OK)
{
/* Read NumberOfBlocks blocks of BufferWordsSize
bytes from address BlockAddress */
SD_state = HAL_SD_ReadBlocks_IT(&hsd_card,
Buffer_Block_Rx,
BlockAddress,
NumberOfBlocks);
}
else
{
Error_Handler();
}
/* Wait for the Reading process is completed */
while(sdtransferrx == 0)
{}
/* Wait for the card transfer status before
proceeding with another SD operation */
while(HAL_SD_GetCardState(&hsd_card)
!= HAL_SD_CARD_TRANSFER)
{}
void TxCpltCallback(SD_HandleTypeDef *hsd) {
sdtransfertx = 1;
}
void RxCpltCallback(SD_HandleTypeDef *hsd) {
sdtransferrx = 1;
}
|
uint8_t Buffer_Block_Tx[BufferWordsSize];
uint8_t Buffer_Block_Rx[BufferWordsSize];
/* Register the Tx and Rx Transfer complete callbacks */
HAL_SD_RegisterXferCpltCallback(&hsd, MySdXferCallback);
/* Write NumberOfBlocks blocks of
BufferWordsSize bytes on address BlockAddress */
SD_state = HAL_SD_WriteBlocks_IT(&hsd_card,
Buffer_Block_Tx,
BlockAddress,
NumberOfBlocks);
/* Wait for the Writing process to complete */
while(sdtransfertx == 0)
{}
/* Wait for the card transfer status
before starting a read operation */
while(HAL_SD_GetCardState(&hsd_card)
!= HAL_SD_CARD_TRANSFER)
{}
if (SD_state == HAL_OK)
{
/* Read NumberOfBlocks blocks of
BufferWordsSize bytes from address BlockAddress */
SD_state = HAL_SD_ReadBlocks_IT(&hsd_card,
Buffer_Block_Rx,
BlockAddress,
NumberOfBlocks);
}
else
{
Error_Handler();
}
/* Wait for the Reading process is completed */
while(sdtransferrx == 0)
{}
/* Wait for the card transfer status
before proceeding with another SD operation */
while(HAL_SD_GetCardState(&hsd_card)
!= HAL_SD_CARD_TRANSFER)
{}
void MySdXferCallback(hal_sd_handle_t *hsd,
hal_sd_event_cb_t cb_event) {
switch (cb_event) {
case HAL_SD_EVENT_CB_TX_CPLT:
sdtransfertx = 1;
break;
case HAL_SD_EVENT_CB_RX_CPLT:
sdtransferrx = 1;
break;
default: break;
}
}
|
HAL SD DMA transfer mode ¶
|
HAL1 |
HAL2 |
|---|---|
|
DMA transfer mode uses
|
DMA transfer sequence remains mostly unchanged between HAL1 and HAL2, but callback registration is unified via
|
Code Snippet (DMA)
uint8_t Buffer_Block_Tx[BufferWordsSize], Buffer_Block_Rx[BufferWordsSize];
/* Write NumberOfBlocks blocks of BufferWordsSize bytes on address BlockAddress */
SD_state = HAL_SD_WriteBlocks_DMA(&hsd_card, Buffer_Block_Tx, BlockAddress, NumberOfBlocks);
/* Wait for the Writing process to complete */
while(sdtransfertx == 0) /* The variable ``sdtransfertx`` is updated by
the callback function */
{}
/* Wait for the card transfer status before starting a read operation */
while(HAL_SD_GetCardState(&hsd_card) != HAL_SD_CARD_TRANSFER)
{}
if (SD_state == HAL_OK)
{
/* Read NumberOfBlocks blocks of BufferWordsSize bytes from address BlockAddress */
SD_state = HAL_SD_ReadBlocks_DMA(&hsd_card, Buffer_Block_Rx, BlockAddress, NumberOfBlocks);
}
else
{
Error_Handler();
}
/* Wait for the Reading process is completed */
while(sdtransferrx == 0) /* The variable ``sdtransferrx`` is updated by
the callback function */
{}
/* Wait for the card transfer status before proceeding with another SD operation */
while(HAL_SD_GetCardState(&hsd_card) != HAL_SD_CARD_TRANSFER)
{}
HAL SD linked-list DMA transfer ¶
|
HAL1 |
HAL2 |
|---|---|
|
Linked-list DMA transfer mode uses linked list node building and insertion APIs (
|
In HAL2 linked-list DMA transfer is updated with most of linked-list management handled by HAL Q driver (a new driver provided with HAL2). The user builds nodes using
|
Code Snippet (Linked-list DMA)
|
HAL1 |
HAL2 |
|---|---|
/****************************************************** Build SDMMC node 1 */
SD_Node_Conf.BufferAddress = (uint32_t) &(Buffer_Tx[0]);
SD_Node_Conf.BufferSize = BLOCKSIZE*1;
HAL_SDEx_DMALinkedList_BuildNode(&SD_N1, &SD_Node_Conf);
/************************************************************ Build node 2 */
SD_Node_Conf.BufferAddress = (uint32_t) &(Buffer_Tx[BufferWordsSize]);
SD_Node_Conf.BufferSize = BLOCKSIZE*2;
HAL_SDEx_DMALinkedList_BuildNode(&SD_N2, &SD_Node_Conf);
/************************************************************ Build node 3 */
SD_Node_Conf.BufferAddress = (uint32_t) &(Buffer_Tx[BufferWordsSize*3]);
SD_Node_Conf.BufferSize = BLOCKSIZE*3;
HAL_SDEx_DMALinkedList_BuildNode(&SD_N3, &SD_Node_Conf);
/* Define list object */
SD_DMALinkedListTypeDef Q_write;
/*********************************************** Connect node 1 to Queue 1 */
HAL_SDEx_DMALinkedList_InsertNode(&Q_write, NULL, &SD_N1);
/*********************************************** Connect node 2 to Queue 1 */
HAL_SDEx_DMALinkedList_InsertNode(&Q_write, &SD_N1, &SD_N2);
/*********************************************** Connect node 3 to Queue 1 */
HAL_SDEx_DMALinkedList_InsertNode(&Q_write, &SD_N2, &SD_N3);
/* Write steps */
/* Write blocks using DMA transfer with linked list */
if (HAL_SDEx_DMALinkedList_WriteBlocks(&hsd_card, &Q_write, 1000, 12) != HAL_OK)
{
Error_Handler();
}
/*************************************************** Wait for TX complete */
while (sdtransfertx == 0)
{}
/******************************************* Wait for card transfer state */
while (HAL_SD_GetCardState(&hsd_card) != HAL_SD_CARD_TRANSFER)
{}
/* Read steps */
SD_Node_Conf.BufferAddress = (uint32_t) &(Buffer_Rx[0]);
SD_Node_Conf.BufferSize = BLOCKSIZE;
HAL_SDEx_DMALinkedList_BuildNode(&SD_N4, &SD_Node_Conf);
SD_Node_Conf.BufferAddress = (uint32_t) &(Buffer_Rx[BufferWordsSize*2]);
SD_Node_Conf.BufferSize = BLOCKSIZE*2;
HAL_SDEx_DMALinkedList_BuildNode(&SD_N5, &SD_Node_Conf);
SD_Node_Conf.BufferAddress = (uint32_t) &(Buffer_Rx[BufferWordsSize*3]);
SD_Node_Conf.BufferSize = BLOCKSIZE*3;
HAL_SDEx_DMALinkedList_BuildNode(&SD_N6, &SD_Node_Conf);
/* Define list object */
SD_DMALinkedListTypeDef Q_read;
HAL_SDEx_DMALinkedList_InsertNode(&Q_read, NULL, &SD_N4);
HAL_SDEx_DMALinkedList_InsertNode(&Q_read, &SD_N4, &SD_N5);
HAL_SDEx_DMALinkedList_InsertNode(&Q_read, &SD_N5, &SD_N6);
/* Read back written block using DMA linked-list transfer */
if (HAL_SDEx_DMALinkedList_ReadBlocks(&hsd_card, &Q_read, 1000,12) != HAL_OK)
{
Error_Handler();
}
/*********************************************** Wait for RX/TX complete */
while (sdtransferrx == 0)
{}
/****************************************** Wait for card transfer state */
while (HAL_SD_GetCardState(&hsd_card) != HAL_SD_CARD_TRANSFER)
{}
|
/**************************************************** Build SDMMC node 1 */
HAL_SD_FillNodeConfig(&SD_N1, &(Buffer_Tx[0]), 1 * BLOCKSIZE);
/********************************************************** Build node 2 */
HAL_SD_FillNodeConfig(&SD_N2, &(Buffer_Tx[BufferWordsSize]), 2 * BLOCKSIZE);
/********************************************************** Build node 3 */
HAL_SD_FillNodeConfig(&SD_N3, &(Buffer_Tx[BufferWordsSize * 3]), 3 * BLOCKSIZE);
/************************************************** HAL Q initialization */
hal_q_t Q_write;
HAL_Q_Init(&Q_write, &HAL_SD_DescOps);
/********************************************* Connect node 1 to Queue 1 */
HAL_Q_InsertNode(&Q_write, NULL, &SD_N1);
/********************************************* Connect node 2 to Queue 1 */
HAL_Q_InsertNode(&Q_write, &SD_N1, &SD_N2);
/********************************************* Connect node 3 to Queue 1 */
HAL_Q_InsertNode(&Q_write, &SD_N2, &SD_N3);
/* Write steps */
/* Write blocks using DMA transfer with linked list */
if ((SD_state = HAL_SD_WriteBlocks_LinkedList(&hsd_card, 1000, 12, &Q_write)) != HAL_OK)
{
Error_Handler();
}
/************************************************** Wait for TX complete */
while(sdtransfertx == 0)
{}
/************************************* Wait for the card transfer status */
while(HAL_SD_GetCardState(&hsd_card) != HAL_SD_CARD_TRANSFER)
{}
/* Read steps */
HAL_SD_FillNodeConfig(&SD_N4, &(Buffer_Rx[0]), 1 * BLOCKSIZE);
HAL_SD_FillNodeConfig(&SD_N5, &(Buffer_Rx[BufferWordsSize*2]), 2 * BLOCKSIZE);
HAL_SD_FillNodeConfig(&SD_N6, &(Buffer_Rx[BufferWordsSize*3]), 3 * BLOCKSIZE);
/************************************************** HAL Q initialization */
hal_q_t Q_read;
HAL_Q_Init(&Q_read, &HAL_SD_DescOps);
HAL_Q_InsertNode(&Q_read, NULL, &SD_N4);
HAL_Q_InsertNode(&Q_read, &SD_N4, &SD_N5);
HAL_Q_InsertNode(&Q_read, &SD_N5, &SD_N6);
/* Read back written block using DMA linked-list transfer */
if (HAL_SD_ReadBlocks_LinkedList(&hsd_card, 1000, 12, &Q_read) != HAL_OK)
{
Error_Handler();
}
/*********************************************** Wait for RX/TX complete */
while ((sdtransferrx == 0))
{}
/****************************************** Wait for card transfer state */
while(HAL_SD_GetCardState(&hsd_card) != HAL_SD_CARD_TRANSFER)
{}
|
HAL SD card removal/insertion handling ¶
Card presence is typically monitored using a dedicated Card Detect (CD) GPIO pin, with EXTI interrupts used to notify the application of insertion or removal events.
|
HAL1 |
HAL2 |
|---|---|
|
In HAL1, upon card removal (detected via EXTI), if there is any ongoing processes (read/write) the application should stop them (for instance stop transfers with
|
In HAL2, the application similarly handles EXTI notifications. On removal, it aborts ongoing processes in the same way but also calls
|
Code Snippet (card removal/insertion)
|
HAL1 |
HAL2 |
|---|---|
volatile uint8_t card_present = 0;
/* Example guarded I/O */
void USER_SD_Application_routine()
{
if (card_present)
{
/* Perform read/write only if card is present */
/* ... */
}
}
/* EXTI callback hooked to the SD card-detect GPIO pin */
void USER_SD_HotPlugCallback()
{
if (USER_SD_READ_DETECT_PIN())
{
/* Card removed */
card_present = 0U;
/* Abort ongoing processes*/
User_SD_StopOngoingProcess(&hsd_card);
}
else
{
/* Card inserted */
HAL_SD_InitCard(&hsd_card);
card_present = 1U;
}
}
|
volatile uint8_t card_present = 0;
/* Example guarded I/O */
void USER_SD_Application_routine()
{
if (card_present)
{
/* Perform read/write only if card is present */
/* ... */
}
}
/* EXTI callback hooked to the SD card-detect GPIO pin */
void USER_SD_HotPlugCallback()
{
if (USER_SD_READ_DETECT_PIN())
{
/* Card removed */
card_present = 0U;
/* Abort ongoing processes*/
USER_SD_StopOngoingProcess(&hsd_card);
HAL_SD_NotifyCardRemoval(&hsd_card);
}
else
{
/* Card inserted */
HAL_SD_NotifyCardInsertion(&hsd_card, &user_config);
card_present = 1U;
}
}
|